package com.oa.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.joneying.common.web.response.Resp;
import com.oa.core.exception.DataIsEmptyException;
import com.oa.core.handler.ApprovalResult;
import com.oa.core.utils.SendMsgManager;
import com.oa.system.dto.ApplyApprovalAddDTO;
import com.oa.system.dto.ApprovalDTO;
import com.oa.system.entity.*;
import com.oa.system.mapper.ApplyApprovalMapper;
import com.oa.system.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Service
public class ApplyApprovalServiceImpl extends ServiceImpl<ApplyApprovalMapper, ApplyApproval> implements IApplyApprovalService {


    @Autowired
    private IApprovalPlanService approvalPlanService;

    @Autowired
    private IApprovalRuleService approvalRuleService;

    @Autowired
    private IApprovalNodeService approvalNodeService;

    @Autowired
    private IApprovalNodeUserService approvalNodeUserService;

    @Autowired
    private IApplyApprovalRecordService applyApprovalRecordService;

    @Autowired
    private IApplyApprovalCopyRecordService applyApprovalCopyRecordService;

    @Autowired
    private IUserService userService;

    @Autowired
    private SendMsgManager sendMsgManager;

    @Autowired
    private IProcessAssemblyService processAssemblyService;

    @Autowired
    private IProcessInfoSubmitService processInfoSubmitService;

    @Override
    public boolean ruleOperationHandle(Object obj, ApprovalRule approvalRule){

        if(approvalRule.getAssemblyId() != null && approvalRule.getAssemblyId() == 0){
            String[] userIds = String.valueOf(obj).split(",");
            for (String userId : userIds) {
                User user = userService.selectById(userId);
                if(user != null){
                    return true;
                }
            }
        }

        if(approvalRule.getRuleStyle() == 1){
            if(obj.toString().equals(approvalRule.getRuleValue())){
                return true;
            }
        }else if(approvalRule.getRuleStyle() == 2){
            if(Double.valueOf(obj.toString()) > Double.valueOf(approvalRule.getRuleValue())){
                return true;
            }
        }else if(approvalRule.getRuleStyle() == 3){
            if(Double.valueOf(obj.toString()) < Double.valueOf(approvalRule.getRuleValue())){
                return true;
            }
        }else if(approvalRule.getRuleStyle() == 4){
            if(Double.valueOf(obj.toString()) >= Double.valueOf(approvalRule.getRuleValue())){
                return true;
            }
        }else if(approvalRule.getRuleStyle() == 5){
            if(Double.valueOf(obj.toString()) <= Double.valueOf(approvalRule.getRuleValue())){
                return true;
            }
        }else if(approvalRule.getRuleStyle() == 6){
            JSONObject jsonObject = JSONObject.parseObject(approvalRule.getRuleValue());
            JSONObject start = jsonObject.getJSONObject("start");
            ApprovalRule startObj = new ApprovalRule();
            startObj.setRuleStyle(start.getInteger("key"));
            startObj.setRuleValue(start.getString("value"));
            startObj.setAssemblyId(approvalRule.getAssemblyId());

            JSONObject end = jsonObject.getJSONObject("end");
            ApprovalRule endObj = new ApprovalRule();
            endObj.setRuleStyle(end.getInteger("key"));
            endObj.setRuleValue(end.getString("value"));
            endObj.setAssemblyId(approvalRule.getAssemblyId());

            if(ruleOperationHandle(obj, startObj) && ruleOperationHandle(obj, endObj)){
                return true;
            }
        }
        return false;
    }

    @Override
    public Long getPlanId(String userId, Map<Long, ProcessInfoSubmit> processInfoSubmitMap, String approvalProcessId){
        boolean stop = false;

        Long planId = Long.valueOf(0);

        List<ApprovalPlan> approvalPlans = approvalPlanService.selectList(new EntityWrapper().eq("approval_process_id", approvalProcessId));
        for (ApprovalPlan approvalPlan : approvalPlans) {
            List<ApprovalRule> approvalRules = approvalRuleService.selectList(new EntityWrapper().eq("approval_plan_id", approvalPlan.getId()));
            for (ApprovalRule approvalRule : approvalRules) {
                ProcessInfoSubmit processInfoSubmit = processInfoSubmitMap.get(approvalRule.getAssemblyId());
                approvalRule.setAssemblyId(approvalRule.getAssemblyId());
                if(processInfoSubmit == null){
                    stop = ruleOperationHandle(userId, approvalRule);
                }else{
                    stop = ruleOperationHandle(processInfoSubmit.getValue(), approvalRule);
                    processInfoSubmitService.insert(processInfoSubmit);
                }
            }
            if(stop == true){
                planId = approvalPlan.getId();
                break;
            }
        }

        if(stop == false){
            ApprovalPlan defaultPlan = approvalPlanService.selectOne(new EntityWrapper().eq("approval_process_id", approvalProcessId).eq("is_default", 1));
            if(defaultPlan != null){
                planId = defaultPlan.getId();
            }
        }

        return planId;
    }


    @Override
    public Resp addApproval(ApplyApprovalAddDTO applyApprovalAddDTO) {
        ApplyApproval applyApproval = new ApplyApproval();
        BeanUtils.copyProperties(applyApprovalAddDTO, applyApproval);
        applyApproval.setStatus(1);

        // 审批方案
        ApprovalPlan approvalPlan = approvalPlanService.selectById(applyApproval.getApprovalPlanId());

        if(approvalPlan == null){
            approvalPlan = approvalPlanService.selectOne(new EntityWrapper().eq("approval_process_id", applyApprovalAddDTO.getApprovalProcessId()).eq("is_default", 1));
            if(approvalPlan == null){
                return new Resp().failure("出错, 无此审批方案");
            }
        }

        ApprovalNode approvalNode = approvalNodeService.selectOne(new EntityWrapper().eq("approval_plan_id", approvalPlan.getId()).orderBy("sort", true));
        if(approvalNode == null){
            applyApproval.setApprovalNodeId(Long.valueOf(0));
            applyApproval.setStatus(2);
        }else{
            applyApproval.setApprovalNodeId(approvalNode.getId());
        }
        applyApproval.setCreateTime(new Date());
        applyApproval.setApprovalPlanId(approvalPlan.getId());

        if(insert(applyApproval)){
            if(approvalNode.getType() == 2){
                List<ApprovalNode> approvalNodes = approvalNodeService.selectList(new EntityWrapper().eq("approval_plan_id", approvalPlan.getId()).orderBy("sort", true));
                approvalNode = nextApprovalNodeHander(applyApproval.getId(), approvalNodes, approvalNode.getSort()).get(0);
                applyApproval.setApprovalNodeId(approvalNode.getId());
                updateById(applyApproval);
            }else {
                //通知审批人
                List<ApprovalNodeUser> approvalNodeUsers = approvalNodeUserService.selectList(new EntityWrapper().eq("approval_node_id", approvalNode.getId()));
                if(approvalNodeUsers != null && approvalNodeUsers.size() > 0){
                    for (ApprovalNodeUser approvalNodeUser : approvalNodeUsers) {
                        ApplyApprovalRecord applyApprovalRecord = new ApplyApprovalRecord();
                        applyApprovalRecord.setStatus(0);
                        applyApprovalRecord.setUserId(approvalNodeUser.getUserId());
                        applyApprovalRecord.setApprovalNodeId(approvalNode.getId());
                        applyApprovalRecord.setCreateTime(new Date());
                        applyApprovalRecord.setApplyApprovalId(applyApproval.getId());
                        applyApprovalRecordService.insert(applyApprovalRecord);

                        User user = userService.selectById(approvalNodeUser.getUserId());
                        if(user != null){
                            sendMsgManager.sendMsg(user, "新审批记录", applyApprovalAddDTO.getApplyApprovalName(), r -> {});
                        }
                    }
                }
            }
            return new Resp().success();
        }
        return new Resp().failure();
    }

    @Override
    public Resp audit(ApprovalDTO approvalDTO) throws DataIsEmptyException {
        if(auditHander(approvalDTO) != null){
            return new Resp().success();
        }
        return new Resp().failure();
    }

    @Override
    public Resp audit(ApprovalDTO approvalDTO, Consumer<ApprovalResult> consumer) throws DataIsEmptyException {
        ApprovalResult approvalResult = auditHander(approvalDTO);
        if(approvalResult != null){
            consumer.accept(approvalResult);
            return new Resp().success();
        }
        throw new DataIsEmptyException("审批失败");
    }

    @Transactional(rollbackFor = Exception.class)
    public ApprovalResult auditHander(ApprovalDTO approvalDTO) throws DataIsEmptyException {
        // 获取申请记录
        ApplyApproval applyApproval = selectById(approvalDTO.getId());
        if(applyApproval == null){
            throw new DataIsEmptyException("无申请记录");
        }

        ApprovalResult approvalResult = new ApprovalResult();

        ApprovalNode currentNode = approvalNodeService.selectById(applyApproval.getApprovalNodeId());

        // 通过操作
        if(approvalDTO.getStatus() == 1){

            // 下一节点处理
            List<ApprovalNode> approvalNodes = approvalNodeService.selectList(
                    new EntityWrapper<ApprovalNode>()
                            .eq("approval_plan_id", applyApproval.getApprovalPlanId())
                            .gt("sort", currentNode.getSort())
                            .orderBy("sort", true)
            );

            if(approvalNodes != null && approvalNodes.size() > 0){
                ApprovalNode nextNode = approvalNodes.get(0);

                List<ApprovalNode> nextApprovalNodes = null;
                if(nextNode.getType() == 2){
                    nextApprovalNodes = nextApprovalNodeHander(applyApproval.getId(), approvalNodes, nextNode.getSort());
                    if(nextApprovalNodes != null && nextApprovalNodes.size() > 0){
                        nextNode = nextApprovalNodes.get(0);
                    }
                }

                if(nextNode.getType() == 1){
                    List<ApprovalNodeUser> nextNodeUsers = approvalNodeUserService.selectList(
                            new EntityWrapper<ApprovalNodeUser>()
                                    .eq("approval_node_id", nextNode.getId())
                    );

                    if(nextNodeUsers != null){
                        if(addApprovalRecord(applyApproval.getId(), nextNodeUsers)){
                            applyApproval.setApprovalNodeId(nextNode.getId());
                        }
                    }
                }else{
                    approvalResult.setLastStatus(true);
                    applyApproval.setApprovalNodeId(Long.valueOf(0));
                    applyApproval.setStatus(3);
                }

            }else{
                applyApproval.setStatus(3);
                approvalResult.setLastStatus(true);
            }
        }else if(approvalDTO.getStatus() == 2){
            applyApproval.setStatus(approvalDTO.getStatus());
        }else{
            //扩展区
        }
        // 改变当前节点用户处理
        List<ApplyApprovalRecord> currentApplyApprovalRecords = applyApprovalRecordService.selectList(
                new EntityWrapper<ApplyApprovalRecord>()
                        .eq("apply_approval_id", applyApproval.getId())
                        .eq("approval_node_id", currentNode.getId())
        );
        currentApplyApprovalRecords.forEach(d -> {
            d.setStatus(approvalDTO.getStatus());
            d.setFinalOperationUserId(approvalDTO.getUserId());
        });
        // 批量修改状态
        applyApprovalRecordService.updateBatchById(currentApplyApprovalRecords);

        if(updateById(applyApproval)){
            if(applyApproval.getStatus() == 3){
                approvalResult.setStatus(2);
            }else{
                approvalResult.setStatus(applyApproval.getStatus());
            }

            approvalResult.setApplyApproval(applyApproval);



            // 通知申请人
            User user = userService.selectById(applyApproval.getApprovalUserId());
            sendMsgManager.sendMsg(user, "审批进度更新", applyApproval.getApplyApprovalName(), r -> {});
        }
        return approvalResult;
    }

    public List<ApprovalNode> nextApprovalNodeHander(Long applyApprovalId, List<ApprovalNode> approvalNodes, Integer sort){
        approvalNodes.sort((a, b) -> a.getSort() - b.getType());

        List<ApprovalNode> handleApprovalNodes = new ArrayList<>();

        for (int i = 0; i < approvalNodes.size(); i++) {
            if(approvalNodes.get(i).getType() == 1){
                handleApprovalNodes.add(approvalNodes.get(i));
                return handleApprovalNodes;
            }else{
                List<ApprovalNodeUser> nextNodeUsers = approvalNodeUserService.selectList(
                        new EntityWrapper<ApprovalNodeUser>()
                                .eq("approval_node_id", approvalNodes.get(i).getId())
                );
                if(!addCopyRecord(applyApprovalId, nextNodeUsers)){
                    ApplyApproval applyApproval = selectById(applyApprovalId);
                    User user = userService.selectById(nextNodeUsers.get(i).getUserId());
                    sendMsgManager.sendMsg(user, user.getName()+"的审批进度更新", applyApproval.getApplyApprovalName(), r -> {});
                    return handleApprovalNodes;
                }
                // 递归处理抄送节点
                nextApprovalNodeHander(applyApprovalId, approvalNodes.stream().filter(d -> d.getSort() > sort).collect(Collectors.toList()), approvalNodes.get(i).getSort());
            }
        }

        return handleApprovalNodes;
    }

    public boolean addApprovalRecord(Long applyApprovalId, List<ApprovalNodeUser> approvalNodeUsers){
        List<ApplyApprovalRecord> nextApplyApprovalRecords = new ArrayList<>();

        approvalNodeUsers.forEach(d -> {
            ApplyApprovalRecord nextApplyApprovalRecord = new ApplyApprovalRecord();
            nextApplyApprovalRecord.setStatus(0);
            nextApplyApprovalRecord.setApplyApprovalId(applyApprovalId);
            nextApplyApprovalRecord.setUserId(d.getUserId());
            nextApplyApprovalRecord.setApprovalNodeId(d.getApprovalNodeId());
            nextApplyApprovalRecord.setCreateTime(new Date());
            nextApplyApprovalRecords.add(nextApplyApprovalRecord);
        });

        // 新增下一节点审批人
        return applyApprovalRecordService.insertBatch(nextApplyApprovalRecords);
    }

    public boolean addCopyRecord(Long applyApprovalId, List<ApprovalNodeUser> approvalNodeUsers){

        List<ApplyApprovalCopyRecord> applyApprovalCopyRecords = new ArrayList<>();

        approvalNodeUsers.forEach(d -> {
            ApplyApprovalCopyRecord applyApprovalCopyRecord = new ApplyApprovalCopyRecord();
            applyApprovalCopyRecord.setUserId(d.getUserId());
            applyApprovalCopyRecord.setApplyApprovalId(applyApprovalId);
            applyApprovalCopyRecord.setCreateTime(new Date());
            applyApprovalCopyRecords.add(applyApprovalCopyRecord);
        });

        return applyApprovalCopyRecordService.insertBatch(applyApprovalCopyRecords);
    }
}
